/*
 * CFileUploadQueue.h
 *
 *  Created on: 2017年11月8日
 *      Author: zhengboyuan
 */

#ifndef CFILEUPLOADQUEUE_H_
#define CFILEUPLOADQUEUE_H_

#include "FileUploadQueue.h"
#include <deque>
#include "TEvent.h"
#include "TCriticalSection.h"
#include "TThread.h"
#include "SharedPtr.h"
#include "CommandThread.h"

class CFileUploadQueue: public FileUploadQueue, util::CommandThread, FileUploadClient::Sink
{
public:
	CFileUploadQueue();
	virtual ~CFileUploadQueue();

	/// 开始
	virtual bool start();

	/// 停止
	virtual void stop();

	/**
	 * 添加文件上传任务
	 * @param tid		任务ID, <= 0 表示自动生成
	 * @param url		上传路径
	 * @param formData	表属性
	 * @param file		上传文件
	 * @return 任务ID, == -1 表示失败
	 */
	virtual int add(int tid, const std::string& url, const StringMap& header, const StringMap& formData, const FileUpload& file);

	/**
	 * 添加多文件上传任务
	 * @param tid		任务ID, <= 0 表示自动生成
	 * @param url		上传路径
	 * @param formData	表属性
	 * @param files		上传文件
	 * @return 任务ID, == -1 表示失败
	 */
	virtual int addMulti(int tid, const std::string& url, const StringMap& header, const StringMap& formData, const FileUploadArray& files);

	/**
	 * 取消上传任务
	 * @param tid	任务ID
	 */
	virtual void cancel(int tid);

	/**
	 * 设置监听
	 * @param listener
	 */
	virtual void setListener(Listener* listener);

	int addTask(FileUploadTask& task);

protected:
	virtual void onCommand(util::Command& cmd);

	virtual void onFileUploadStatus(FileUploadClient* client, int status, const std::string& result);

	virtual void onFileUploadProgress(FileUploadClient* client, int total, int sent);

protected:
	enum CommandType
	{
		kCmdAddTask = util::Command::kUser + 1,
		kCmdRemoveTask,
		kCmdUploadEnd,
		kCmdUploadError
	};
protected:

	int makeTaskId();
	bool existTaskId(int tid);
	bool removeTask(int tid, FileUploadTask& task);

	void handleCancelUpload(int tid);
	void handleAddTask();
	void handleUploadEnd(int tid);
	void handleUploadError(int tid);

	bool waitForTask(FileUploadTask& task, int ms);
	bool fetchTask(FileUploadTask& task);

	bool tryStartTask();

protected:
	typedef std::deque< FileUploadTask >	FileUploadTaskDeque;
	typedef std::shared_ptr< FileUploadClient >	FileUploadClientPtr;

	FileUploadTaskDeque	m_tasks;

	comn::CriticalSection	m_cs;
	Listener*	m_listener;

	int	m_nextTaskId;

	FileUploadClientPtr	m_client;
	FileUploadTask	m_curTask;

};

#endif /* CFILEUPLOADQUEUE_H_ */
